from mcp.server.fastmcp import FastMCP
import math
import logging
from typing import Union

# 配置日志
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)

# Create an MCP server
mcp = FastMCP("Enhanced Calculator and Greeting Server")

@mcp.tool()
def say_hello(name: str) -> str:
    """生成个性化问候语"""
    try:
        if not name or not name.strip():
            raise ValueError("用户名不能为空")
        name = name.strip()
        if len(name) > 50:
            raise ValueError("用户名过长")
        result = f"你好，{name}！欢迎使用增强版计算器服务！我可以帮您进行各种数学运算。"
        logger.info(f"问候用户: {name}")
        return result
    except Exception as e:
        logger.error(f"问候功能错误: {e}")
        raise ValueError(f"问候失败: {e}")

@mcp.tool()
def say_goodbye(name: str) -> str:
    """生成个性化告别语"""
    try:
        if not name or not name.strip():
            raise ValueError("用户名不能为空")
        name = name.strip()
        if len(name) > 50:
            raise ValueError("用户名过长")
        result = f"再见，{name}！感谢使用增强版计算器服务！期待下次为您服务。"
        logger.info(f"告别用户: {name}")
        return result
    except Exception as e:
        logger.error(f"告别功能错误: {e}")
        raise ValueError(f"告别失败: {e}")

@mcp.tool()
def add(a: float, b: float) -> float:
    """
    加法运算
    :param a: 加数
    :param b: 加数
    :return: 和
    """
    try:
        result = a + b
        logger.info(f"加法运算: {a} + {b} = {result}")
        return result
    except Exception as e:
        logger.error(f"加法运算错误: {e}")
        raise ValueError(f"加法运算失败: {e}")

@mcp.tool()
def subtract(a: float, b: float) -> float:
    """
    减法运算
    :param a: 被减数
    :param b: 减数
    :return: 差
    """
    try:
        result = a - b
        logger.info(f"减法运算: {a} - {b} = {result}")
        return result
    except Exception as e:
        logger.error(f"减法运算错误: {e}")
        raise ValueError(f"减法运算失败: {e}")

@mcp.tool()
def multiply(a: float, b: float) -> float:
    """
    乘法运算
    :param a: 乘数
    :param b: 乘数
    :return: 积
    """
    try:
        result = a * b
        logger.info(f"乘法运算: {a} × {b} = {result}")
        return result
    except Exception as e:
        logger.error(f"乘法运算错误: {e}")
        raise ValueError(f"乘法运算失败: {e}")

@mcp.tool()
def divide(a: float, b: float) -> float:
    """
    除法运算
    :param a: 被除数
    :param b: 除数
    :return: 商
    :raises ValueError: 当除数为零时抛出
    """
    try:
        if b == 0:
            raise ValueError("除数不能为零")
        if math.isinf(a) or math.isnan(a) or math.isinf(b) or math.isnan(b):
            raise ValueError("输入包含无效数值")
        result = a / b
        logger.info(f"除法运算: {a} ÷ {b} = {result}")
        return result
    except Exception as e:
        logger.error(f"除法运算错误: {e}")
        raise ValueError(f"除法运算失败: {e}")

@mcp.tool()
def square(x: float) -> float:
    """计算平方值"""
    try:
        if math.isinf(x) or math.isnan(x):
            raise ValueError("输入包含无效数值")
        result = x * x
        logger.info(f"平方运算: {x}² = {result}")
        return result
    except Exception as e:
        logger.error(f"平方运算错误: {e}")
        raise ValueError(f"平方运算失败: {e}")

@mcp.tool()
def square_root(x: float) -> float:
    """计算平方根"""
    try:
        if x < 0:
            raise ValueError("输入值不能为负数")
        if math.isinf(x) or math.isnan(x):
            raise ValueError("输入包含无效数值")
        result = math.sqrt(x)
        logger.info(f"平方根运算: √{x} = {result}")
        return result
    except Exception as e:
        logger.error(f"平方根运算错误: {e}")
        raise ValueError(f"平方根运算失败: {e}")

@mcp.tool()
def absolute(x: float) -> float:
    """计算绝对值"""
    try:
        if math.isinf(x) or math.isnan(x):
            raise ValueError("输入包含无效数值")
        result = abs(x)
        logger.info(f"绝对值运算: |{x}| = {result}")
        return result
    except Exception as e:
        logger.error(f"绝对值运算错误: {e}")
        raise ValueError(f"绝对值运算失败: {e}")

@mcp.tool()
def power(base: float, exponent: float) -> float:
    """计算幂运算"""
    try:
        if math.isinf(base) or math.isnan(base) or math.isinf(exponent) or math.isnan(exponent):
            raise ValueError("输入包含无效数值")
        result = math.pow(base, exponent)
        logger.info(f"幂运算: {base}^{exponent} = {result}")
        return result
    except Exception as e:
        logger.error(f"幂运算错误: {e}")
        raise ValueError(f"幂运算失败: {e}")

@mcp.tool()
def sin(x: float) -> float:
    """计算正弦值（输入为弧度）"""
    try:
        if math.isinf(x) or math.isnan(x):
            raise ValueError("输入包含无效数值")
        result = math.sin(x)
        logger.info(f"正弦运算: sin({x}) = {result}")
        return result
    except Exception as e:
        logger.error(f"正弦运算错误: {e}")
        raise ValueError(f"正弦运算失败: {e}")

@mcp.tool()
def cos(x: float) -> float:
    """计算余弦值（输入为弧度）"""
    try:
        if math.isinf(x) or math.isnan(x):
            raise ValueError("输入包含无效数值")
        result = math.cos(x)
        logger.info(f"余弦运算: cos({x}) = {result}")
        return result
    except Exception as e:
        logger.error(f"余弦运算错误: {e}")
        raise ValueError(f"余弦运算失败: {e}")

@mcp.tool()
def tan(x: float) -> float:
    """计算正切值（输入为弧度）"""
    try:
        if math.isinf(x) or math.isnan(x):
            raise ValueError("输入包含无效数值")
        result = math.tan(x)
        logger.info(f"正切运算: tan({x}) = {result}")
        return result
    except Exception as e:
        logger.error(f"正切运算错误: {e}")
        raise ValueError(f"正切运算失败: {e}")

@mcp.tool()
def log(x: float, base: float = 10) -> float:
    """计算对数"""
    try:
        if x <= 0:
            raise ValueError("对数的真数必须大于0")
        if base <= 0 or base == 1:
            raise ValueError("对数的底数必须大于0且不等于1")
        if math.isinf(x) or math.isnan(x) or math.isinf(base) or math.isnan(base):
            raise ValueError("输入包含无效数值")
        result = math.log(x, base)
        logger.info(f"对数运算: log_{base}({x}) = {result}")
        return result
    except Exception as e:
        logger.error(f"对数运算错误: {e}")
        raise ValueError(f"对数运算失败: {e}")

@mcp.tool()
def ln(x: float) -> float:
    """计算自然对数"""
    try:
        if x <= 0:
            raise ValueError("自然对数的真数必须大于0")
        if math.isinf(x) or math.isnan(x):
            raise ValueError("输入包含无效数值")
        result = math.log(x)
        logger.info(f"自然对数运算: ln({x}) = {result}")
        return result
    except Exception as e:
        logger.error(f"自然对数运算错误: {e}")
        raise ValueError(f"自然对数运算失败: {e}")

@mcp.tool()
def factorial(x: int) -> int:
    """计算阶乘"""
    try:
        if x < 0:
            raise ValueError("阶乘的输入必须是非负整数")
        if x > 170:  # 防止溢出
            raise ValueError("输入值过大，可能导致溢出")
        result = math.factorial(x)
        logger.info(f"阶乘运算: {x}! = {result}")
        return result
    except Exception as e:
        logger.error(f"阶乘运算错误: {e}")
        raise ValueError(f"阶乘运算失败: {e}")

@mcp.tool()
def degrees_to_radians(degrees: float) -> float:
    """将角度转换为弧度"""
    try:
        if math.isinf(degrees) or math.isnan(degrees):
            raise ValueError("输入包含无效数值")
        result = math.radians(degrees)
        logger.info(f"角度转弧度: {degrees}° = {result} rad")
        return result
    except Exception as e:
        logger.error(f"角度转弧度错误: {e}")
        raise ValueError(f"角度转弧度失败: {e}")

@mcp.tool()
def radians_to_degrees(radians: float) -> float:
    """将弧度转换为角度"""
    try:
        if math.isinf(radians) or math.isnan(radians):
            raise ValueError("输入包含无效数值")
        result = math.degrees(radians)
        logger.info(f"弧度转角度: {radians} rad = {result}°")
        return result
    except Exception as e:
        logger.error(f"弧度转角度错误: {e}")
        raise ValueError(f"弧度转角度失败: {e}")

@mcp.tool()
def exp(x: float) -> float:
    """计算e的x次幂"""
    try:
        if math.isinf(x) or math.isnan(x):
            raise ValueError("输入包含无效数值")
        if x > 700:  # 防止溢出
            raise ValueError("指数过大，可能导致溢出")
        result = math.exp(x)
        logger.info(f"指数运算: e^{x} = {result}")
        return result
    except Exception as e:
        logger.error(f"指数运算错误: {e}")
        raise ValueError(f"指数运算失败: {e}")

@mcp.tool()
def ceil(x: float) -> int:
    """向上取整"""
    try:
        if math.isinf(x) or math.isnan(x):
            raise ValueError("输入包含无效数值")
        result = math.ceil(x)
        logger.info(f"向上取整: ceil({x}) = {result}")
        return result
    except Exception as e:
        logger.error(f"向上取整错误: {e}")
        raise ValueError(f"向上取整失败: {e}")

@mcp.tool()
def floor(x: float) -> int:
    """向下取整"""
    try:
        if math.isinf(x) or math.isnan(x):
            raise ValueError("输入包含无效数值")
        result = math.floor(x)
        logger.info(f"向下取整: floor({x}) = {result}")
        return result
    except Exception as e:
        logger.error(f"向下取整错误: {e}")
        raise ValueError(f"向下取整失败: {e}")

@mcp.tool()
def round_number(x: float, digits: int = 0) -> float:
    """四舍五入到指定小数位数"""
    try:
        if math.isinf(x) or math.isnan(x):
            raise ValueError("输入包含无效数值")
        if digits < 0 or digits > 15:
            raise ValueError("小数位数必须在0-15之间")
        result = round(x, digits)
        logger.info(f"四舍五入: round({x}, {digits}) = {result}")
        return result
    except Exception as e:
        logger.error(f"四舍五入错误: {e}")
        raise ValueError(f"四舍五入失败: {e}")

if __name__ == "__main__":
    mcp.run(transport="stdio")